package com.bdk.middle.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bdk.middle.common.domain.PageDO;
import com.bdk.middle.common.result.ResultDO;
import com.bdk.middle.common.status.ErrorCode;
import com.bdk.middle.common.util.BeanUtilsExtends;
import com.bdk.middle.common.util.Constant;
import com.bdk.middle.common.util.SnowflakeIdWorker;
import com.bdk.middle.goods.api.client.GoodsClientApi;
import com.bdk.middle.goods.api.client.SkuClientApi;
import com.bdk.middle.order.api.client.OrderClientApi;
import com.bdk.middle.order.api.domain.OrderDO;
import com.bdk.middle.order.api.domain.GoodsItemDO;
import com.bdk.middle.order.api.domain.OrderItemDO;
import com.bdk.middle.order.api.query.OrderQueryDO;
import com.bdk.middle.order.core.entity.OrderEntity;
import com.bdk.middle.order.core.mapper.OrderMapper;
import com.bdk.middle.order.service.OrderItemService;
import com.bdk.middle.order.service.OrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Reagan
 * @since 2021-03-18
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderEntity> implements OrderService, OrderClientApi {

    private Logger logger = LoggerFactory.getLogger(this.getClass().getName());

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderItemService orderItemService;

    @Autowired
    private GoodsClientImpl goodsClientImpl;

    @Autowired
    private SkuClientImpl skuClientImpl;

    @FeignClient(value= "goods-service", contextId="goods", path = "/app")
    interface GoodsClientImpl extends GoodsClientApi {

    }

    @FeignClient(value= "goods-service", contextId="sku", path = "/app")
    interface SkuClientImpl extends SkuClientApi {

    }

    @Override
    public ResultDO add(OrderDO domain) {

        OrderEntity entity = new OrderEntity();
        ResultDO result = BeanUtilsExtends.copy(entity, domain);
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }
        entity.setCreateDate(Calendar.getInstance().getTime());
        entity.setStatus(Constant.ORDER_STATUS_WAIT_PAY);
        entity.setOrderNo(SnowflakeIdWorker.getNo());
        entity.setIsDelete(Constant.IS_DELETE_FALSE);
        int res = -1;
        try {
            res = orderMapper.insert(entity);
        } catch(Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(res < 0) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.ORDER_ADD_ERROR);
            logger.debug("error code：" + ErrorCode.ORDER_ADD_ERROR.getCode() + " msg" + ErrorCode.ORDER_ADD_ERROR.getMsg());
            return result;
        }
        if(domain.getGoodsItemList() == null) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.ORDER_ITEM_NULL_ERROR);
            logger.debug("error code：" + ErrorCode.ORDER_ITEM_NULL_ERROR.getCode() + " msg" + ErrorCode.ORDER_ITEM_NULL_ERROR.getMsg());
            return result;
        }

        result = setOrderItem(entity.getId(), domain.getGoodsItemList());

        return result;
    }

    private ResultDO setOrderItem(String id, List<GoodsItemDO> goodsItemList) {

        ResultDO result = new ResultDO();

        for(GoodsItemDO domain : goodsItemList) {
            result = goodsClientImpl.get(domain.getGoodsId());
            if(!result.isSuccess()) {
                logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
                return result;
            }

            Map<String, Object> goodsMap = (Map<String, Object>) result.getModel(ResultDO.FIRST_MODEL_KEY);
            OrderItemDO orderItemDO = new OrderItemDO();
            orderItemDO.setOrderId(id);
            orderItemDO.setGoodsName((String) goodsMap.get("name"));
            orderItemDO.setGoodsNo((String) goodsMap.get("goodsNo"));
            orderItemDO.setGoodsCount(domain.getCount());
            int supplyMethod = (int) goodsMap.get("supplyMethod");
            if(supplyMethod == Constant.GOODS_DELIVERY_VIRTUAL) {
                orderItemDO.setIsVirtual(Constant.GOODS_VIRTUAL_TRUE);
            } else {
                orderItemDO.setIsVirtual(Constant.GOODS_VIRTUAL_FALSE);
            }
            StringBuilder attribute = new StringBuilder();
            BigDecimal price = new BigDecimal(0.00);
            for(String skuId : domain.getSkuIds()) {
                result = skuClientImpl.get(skuId);
                Map<String, Object> skuMap = (Map<String, Object>) result.getModel(ResultDO.FIRST_MODEL_KEY);
                attribute.append(skuMap.get("name")).append("/n");
                price = price.add((BigDecimal) skuMap.get("price"));
            }
            orderItemDO.setGoodsAttr(attribute.toString());
            orderItemDO.setGoodsPrice(price);
            result = orderItemService.add(orderItemDO);
            if(!result.isSuccess()) {
                logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
                return result;
            }
        }
        return result;
    }


    @Override
    public ResultDO edit(OrderDO domain) {

        OrderEntity entity = new OrderEntity();

        ResultDO result = BeanUtilsExtends.copy(entity, domain);
        if (!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }
        int res = -1;
        try {
            res = orderMapper.updateById(entity);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(res < 0) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.ORDER_EDIT_ERROR);
            logger.debug("error code：" + ErrorCode.ORDER_EDIT_ERROR.getCode() + " msg" + ErrorCode.ORDER_EDIT_ERROR.getMsg());
            return result;
        }

        return result;
    }

    @Override
    public ResultDO updateStatus(String id, int status) {

        ResultDO result = new ResultDO();
        OrderEntity entity = new OrderEntity();
        entity.setId(id);
        entity.setStatus(status);
        int res = -1;
        try {
            res = orderMapper.updateById(entity);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(res < 0) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.ORDER_DELIVERY_EDIT_ERROR);
            logger.debug("error code：" + ErrorCode.ORDER_DELIVERY_EDIT_ERROR.getCode() + " msg" + ErrorCode.ORDER_DELIVERY_EDIT_ERROR.getMsg());
            return result;
        }

        return result;
    }


    @Override
    public ResultDO get(String id) {
        ResultDO result = new ResultDO();

        OrderEntity entity = null;

        try {
            entity = orderMapper.selectById(id);
        } catch(Exception e) {
            e.printStackTrace();
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        result = orderItemService.getByOrderId(id);

        if(!result.isSuccess()) {
            logger.debug("error code：" + result.getErrorCode().getCode() + " msg" + result.getErrorCode().getMsg());
            return result;
        }

        List<OrderItemDO> orderItemList = (List<OrderItemDO>) result.getModel(ResultDO.FIRST_MODEL_KEY);
        OrderDO domain = getDomain(entity);
        BigDecimal amount = orderItemList.stream().map(OrderItemDO::getGoodsPrice).reduce(BigDecimal.ZERO,BigDecimal::add);
        domain.setOrderItemList(orderItemList);
        domain.setAmount(amount);
        result.setModel(ResultDO.FIRST_MODEL_KEY, domain);

        return result;
    }

    @Override
    public ResultDO remove(String id, String modifier) {

        ResultDO result = new ResultDO();

        OrderEntity entity = new OrderEntity();

        entity.setId(id);

        int res = -1;
        try {
            res = orderMapper.updateById(entity);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        //判断r的值是否小于0.如果小于0 就代表添加失败
        if(res < 0) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.ORDER_DELETE_ERROR);
            logger.debug("error code：" + ErrorCode.ORDER_DELETE_ERROR.getCode() + " msg" + ErrorCode.ORDER_DELETE_ERROR.getMsg());
            return result;
        }
        result = orderItemService.removeByOrderId(id);

        return result;
    }

    @Override
    public ResultDO find(OrderQueryDO query) {

        ResultDO result = new ResultDO();

        QueryWrapper<OrderEntity> wrapper = new QueryWrapper<>();
        if(StringUtils.isNotEmpty(query.getAppId())) {
            wrapper.eq("app_id", query.getAppId());
        }
        if(StringUtils.isNotEmpty(query.getMemberId())) {
            wrapper.eq("member_id", query.getMemberId());
        }
        if(StringUtils.isNotEmpty(query.getOrderNo())) {
            wrapper.eq("order_no", query.getOrderNo());
        }
        if(StringUtils.isNotEmpty(query.getTransactionNo())) {
            wrapper.eq("transaction_no", query.getTransactionNo());
        }
        if(query.getPayStatus() != null) {
            wrapper.eq("pay_status", query.getPayStatus());
        }
        if(query.getDeliveryStatus() != null) {
            wrapper.eq("delivery_status", query.getDeliveryStatus());
        }


        wrapper.eq("is_delete", Constant.IS_DELETE_FALSE);

        Page<OrderEntity> page = new Page<>(query.getCurrentPage(),query.getPageSize());
        IPage<OrderEntity> iPage = null;
        try {
            iPage = orderMapper.selectPage(page, wrapper);
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorCode(ErrorCode.SYSTEM_EXCEPTION);
            logger.debug("error code：" + ErrorCode.SYSTEM_EXCEPTION.getCode() + " msg" + ErrorCode.SYSTEM_EXCEPTION.getMsg());
            return result;
        }

        List<OrderDO> doList = getDomainList(iPage.getRecords());

        PageDO<OrderDO> pageDO = new PageDO<>();

        pageDO.setCurrentPage(iPage.getCurrent());
        pageDO.setPageCount(iPage.getPages());
        pageDO.setPageSize(iPage.getSize());
        pageDO.setRowCount(iPage.getTotal());
        pageDO.setData(doList);

        result.setModel(ResultDO.FIRST_MODEL_KEY, pageDO);
        return result;
    }

    private OrderDO getDomain(OrderEntity entity) {
        ResultDO result = new ResultDO();
        //判断房源对象是否为空，为空就返回 空，不为空就进行下面的代码
        if(entity == null) return null;
        OrderDO domain = new OrderDO();

        if(!result.isSuccess()) {
            return null;
        }
        domain = BeanUtilsExtends.copyProperties(domain, entity) ? domain : null;

        //判断拷贝数据到Dto对象是否成功，如果成功则返回domian，如果不成功就返回空
        return domain;
    }


    private List<OrderDO> getDomainList(List<OrderEntity> list) {
        //创建一个名为dolist的房源do类型的 list集合
        List<OrderDO> doList = new ArrayList<>();

        //判断传入的list的集合的size是否大于0
        if(list.size() > 0) {
            //大于0是，遍历list，创建do类型的对象 调用getdomain方法
            for(OrderEntity entity : list) {

                OrderDO domain = this.getDomain(entity);

                //判断得到的domain 是否为空 不为空 就往dolist集合里面添加domian 为空就返回空
                if(domain == null) {
                    return null;
                }
                doList.add(domain);
            }
        } else {
            return null;
        }
        return doList;
    }
}
